package com.chenfan.ccp.util.tool;


import com.chenfan.ccp.plug.http.annotation.UrlAuth;
import org.springframework.web.bind.annotation.RestController;

import javax.tools.ToolProvider;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 扫描配置类
 */
public class ScannerUtil {

    private static final String SCANNER_CLASS_KEY = "scanner:class:key";
    private static final String SCANNER_FILE_KEY = "scanner:file:key";
    private static final String SUFFIX_NAME = ".java";
    private static final String STATIC_FILE_NAME = "/public";
    private static final String TMP_FILE_PATH = System.getProperty("java.io.tmpdir") + File.separatorChar + "java" + File.separatorChar;
    private static final String JAR_SAVE_FILE = System.getProperty("java.io.tmpdir") + File.separatorChar + "scanner" + File.separatorChar;


    /**
     * 提交的代码片段
     */
    private static final String SUBMIT_STR = "\n" +
            "function ajax(opt) {\n" +
            "    opt = opt || {};\n" +
            "    opt.type = opt.type || \"post\";\n" +
            "    opt.url = opt.url || \"\";\n" +
            "    opt.async = opt.async || true;\n" +
            "    opt.data = opt.data || {};\n" +
            "    opt.headers = opt.headers || {}\n" +
            "    opt.success = opt.success || function () {\n" +
            "    };\n" +
            "    opt.error = opt.error || function () {\n" +
            "    };\n" +
            "\n" +
            "    var jsonFlag = false\n" +
            "\n" +
            "    var xhr = new createxmlHttpRequest();\n" +
            "    var sendData = opt.data\n" +
            "  if (!(opt.data instanceof FormData) && opt.data != null) {\n" +
            "\n" +
            "        //判断json是否在里面\n" +
            "        if (opt.data.hasOwnProperty(JSON_VARIABLE)) {\n" +
            "            jsonFlag = true;\n" +
            "            sendData = opt.data[JSON_VARIABLE]\n" +
            "\n" +
            "        } else {\n" +
            "\n" +
            "            //判断是否是json传递数据\n" +
            "            if (typeof opt.data == 'object') {\n" +
            "                //进行json传递数据解析\n" +
            "                var params = [];\n" +
            "                for (var key in opt.data) {\n" +
            "                    params.push(key + \"=\" + opt.data[key]);\n" +
            "                }\n" +
            "                sendData = params.join(\"&\");\n" +
            "            } else {\n" +
            "                //进行正常的导入\n" +
            "                sendData = opt.data\n" +
            "            }\n" +
            "\n" +
            "\n" +
            "        }\n" +
            "\n" +
            "\n" +
            "    }" +
            "    var headers = opt.headers\n" +
            "\n" +
            "\n" +
            "    if (opt.type.toUpperCase() == \"GET\") {\n" +
            "        xhr.open(opt.type, opt.url + (sendData.trim().length == 0 ? \"\" : \"?\" + sendData), opt.async);\n" +
            "\n" +
            "        for (var key in headers) {\n" +
            "            xhr.setRequestHeader(key, headers[key])\n" +
            "        }\n" +
            "\n" +
            "        xhr.send(null);\n" +
            "\n" +
            "    } else {\n" +
            "        xhr.open(opt.type, opt.url, opt.async);\n" +
            "\n" +
            "        for (var key in headers) {\n" +
            "            xhr.setRequestHeader(key, headers[key])\n" +
            "        }\n" +
            "\n" +
            "\n" +
            "        if (!(opt.data instanceof FormData)) {\n" +
            "            xhr.setRequestHeader(\"Content-type\", \"application/\" +\n" +
            "                (jsonFlag ? \"json\" : \"x-www-form-urlencoded\") + \"; charset=utf-8\");\n" +
            "        }\n" +
            "        xhr.send(sendData);\n" +
            "    }\n" +
            "\n" +
            "    xhr.onreadystatechange = function () {\n" +
            "        if (xhr.readyState == 4) {\n" +
            "            if (xhr.status == 200) {\n" +
            "                opt.success && opt.success(xhr.responseText, sendData);\n" +
            "            } else {\n" +
            "                opt.error && opt.error(xhr.status);\n" +
            "            }\n" +
            "        }\n" +
            "    }\n" +
            "}\n" +
            "\n" +
            "function createxmlHttpRequest() {\n" +
            "    if (window.ActiveXObject) {\n" +
            "        return new ActiveXObject(\"Microsoft.XMLHTTP\");\n" +
            "    } else if (window.XMLHttpRequest) {\n" +
            "        return new XMLHttpRequest();\n" +
            "    }\n" +
            "}\n" +
            "\n" +
            "const JSON_VARIABLE = \"__j_s_o_n__\"\n" +
            "var JSON_SUCCESS = {}\n" +
            "\n" +
            "function append(id) {\n" +
            "\n" +
            "    var newHtmlId = new Date().getTime()\n" +
            "    var html = \"<div style='display: inline' id='\" + newHtmlId + \"'> header的健值对\\n\" +\n" +
            "        \"<input type=\\\"text\\\" placeholder=\\\"header的key\\\">\\n\" +\n" +
            "        \"<input type=\\\"text\\\" placeholder=\\\"header的value\\\">\" +\n" +
            "        \"<button style='background-color:#f44336;color:#fff;font-size:13px;border-radius:35%' onclick='document.getElementById(\" + newHtmlId + \").style.display=\\\"none\\\"'>删除</button>\" +\n" +
            "        \"</div>\"\n" +
            "    var newDivHtml = document.createElement(\"div\");\n" +
            "    newDivHtml.innerHTML = html\n" +
            "    document.getElementById(\"'\" + id + \"'\").appendChild(newDivHtml)\n" +
            "\n" +
            "}\n" +
            "\n" +
            "\n" +
            "function send(param, type, url, index) {\n" +
            "\n" +
            "    var appendId = url\n" +
            "\n" +
            "    var data = {};\n" +
            "    if (param != '') {\n" +
            "        var uploadFlag = false\n" +
            "        var params = param.split(\"&\");\n" +
            "\n" +
            "        params.forEach(function (v) {\n" +
            "\n" +
            "            var _obj = document.getElementById(v + index)\n" +
            "            var _input_type = _obj.getAttribute(\"type\")\n" +
            "            if (_input_type == \"file\") {\n" +
            "                uploadFlag = true\n" +
            "                return\n" +
            "            } else if (_input_type == \"hidden\") {\n" +
            "                try {\n" +
            "                    if (!JSON_SUCCESS[url + v]) {\n" +
            "                        JSON_SUCCESS[url + v] = _obj.parentNode.children[1].innerHTML\n" +
            "                    }\n" +
            "                    data[JSON_VARIABLE] = JSON.stringify(JSON.parse(_obj.parentNode.children[1].innerHTML))\n" +
            "\n" +
            "                } catch (e) {\n" +
            "                    _obj.parentNode.children[1].innerHTML = JSON_SUCCESS[url + v]\n" +
            "                }\n" +
            "\n" +
            "\n" +
            "            } else {\n" +
            "                data[v] = _obj.value\n" +
            "            }\n" +
            "\n" +
            "\n" +
            "        });\n" +
            "\n" +
            "\n" +
            "        if (uploadFlag) {\n" +
            "            data = new FormData()\n" +
            "\n" +
            "            params.forEach(function (v) {\n" +
            "\n" +
            "                var _obj = document.getElementById(v + index)\n" +
            "                var _input_type = _obj.getAttribute(\"type\")\n" +
            "                if (_input_type == \"file\") {\n" +
            "\n" +
            "                    if (_obj.files[0]) {\n" +
            "                        data.append(v, _obj.files[0])\n" +
            "                    }\n" +
            "\n" +
            "\n" +
            "                } else if (_input_type == \"hidden\") {\n" +
            "                    try {\n" +
            "                        if (!JSON_SUCCESS[url + v]) {\n" +
            "                            JSON_SUCCESS[url + v] = _obj.parentNode.children[1].innerHTML\n" +
            "                        }\n" +
            "                        data[JSON_VARIABLE] = JSON.stringify(JSON.parse(_obj.parentNode.children[1].innerHTML))\n" +
            "\n" +
            "                    } catch (e) {\n" +
            "                        _obj.parentNode.children[1].innerHTML = JSON_SUCCESS[url + v]\n" +
            "                    }\n" +
            "\n" +
            "                } else {\n" +
            "                    data.append(v, _obj.value)\n" +
            "                }\n" +
            "\n" +
            "\n" +
            "            });\n" +
            "\n" +
            "\n" +
            "        }\n" +
            "\n" +
            "    }\n" +
            "\n" +
            "    var headers = {}\n" +
            "\n" +
            "    var headerDoms = document.getElementById(\"'____\" + url + (param != '' ? index + 1 : index) + \"'\").querySelectorAll(\"div\")\n" +
            "\n" +
            "\n" +
            "    if (headerDoms) {\n" +
            "\n" +
            "        headerDoms.forEach(function (v) {\n" +
            "\n" +
            "            if (v.style.display == 'inline') {\n" +
            "                var headerNode = v.querySelectorAll(\"input\")\n" +
            "\n" +
            "                if (headerNode[0].value != \"\" && headerNode[1].value != '') {\n" +
            "                    headers[headerNode[0].value] = headerNode[1].value\n" +
            "                }\n" +
            "\n" +
            "            }\n" +
            "\n" +
            "        })\n" +
            "    }\n" +
            "\n" +
            "    //restful\n" +
            "    if (/{(.*)+}/g.test(url)) {\n" +
            "        var newDate = {}\n" +
            "\n" +
            "        for (var k in data) {\n" +
            "            var reg = new RegExp(\"{\" + k + \"(:.+)?}\", \"g\");\n" +
            "            if (reg.test(url)) {\n" +
            "                url = url.replace(reg, data[k])\n" +
            "            } else {\n" +
            "                newDate[k] = data[k]\n" +
            "            }\n" +
            "\n" +
            "        }\n" +
            "\n" +
            "        data = newDate\n" +
            "\n" +
            "\n" +
            "    }\n" +
            "\n" +
            "    ajax({\n" +
            "        type: type,\n" +
            "        url: BASE_PATH_URL + url.split(\",\")[0],\n" +
            "        data: data,\n" +
            "        headers: headers,\n" +
            "        success: function (res, urlParam) {\n" +
            "\n" +
            "            //判断是否是json\n" +
            "            try {\n" +
            "                JSON.parse(res);\n" +
            "            } catch (e) {\n" +
            "                //增加下载的窗口\n" +
            "                return window.open(url + \"?\" + urlParam)\n" +
            "\n" +
            "            }\n" +
            "            appendMsg(appendId, res)\n" +
            "\n" +
            "        },\n" +
            "        error: function (res) {\n" +
            "            appendMsg(appendId, JSON.stringify({'请求错误,原因': '<a style=\\'color: red\\'>' + res + '</a>'}))\n" +
            "        }\n" +
            "    })\n" +
            "\n" +
            "}\n" +
            "\n" +
            "\n" +
            "function appendMsg(appendId, res) {\n" +
            "    var appendAreaId = \"append_\" + appendId\n" +
            "    var msgId = document.getElementById(appendAreaId);\n" +
            "\n" +
            "    if (msgId != undefined) {\n" +
            "        msgId.innerHTML = \"\"\n" +
            "    } else {\n" +
            "        msgId = document.createElement(\"text\");\n" +
            "        msgId.id = appendAreaId;\n" +
            "\n" +
            "    }\n" +
            "\n" +
            "    var appendShowId = \"pre_\" + appendId\n" +
            "    var max_line = 100;\n" +
            "\n" +
            "    msgId.innerHTML = \"<pre id='\" + appendShowId + \"' style='text-overflow: ellipsis;overflow: hidden; display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: \" + max_line + \";' id='\" + appendId + \"'>\" + JSON.stringify(JSON.parse(res), null, 2) + \"</pre>\";\n" +
            "\n" +
            "    insertAfter(msgId, document.getElementById(\"'\" + appendId + \"'\"));\n" +
            "\n" +
            "    //添加显示更多\n" +
            "    if (countLines(appendShowId) >= max_line) {\n" +
            "        var moreEle = document.createElement(\"a\");\n" +
            "        moreEle.id = \"more_\" + appendId\n" +
            "        moreEle.href = \"javascript:clearMore(\\\"\" + appendId + \"\\\")\";\n" +
            "        moreEle.innerText = \"点击查看更多\";\n" +
            "        msgId.appendChild(moreEle);\n" +
            "\n" +
            "    }\n" +
            "\n" +
            "}\n" +
            "\n" +
            "function clearMore(commonId) {\n" +
            "    document.getElementById(\"pre_\" + commonId).style.webkitLineClamp = 999999;\n" +
            "    document.getElementById(\"more_\" + commonId).style.display = \"none\";\n" +
            "}\n" +
            "\n" +
            "\n" +
            "//统计行数\n" +
            "function countLines(ele) {\n" +
            "    var styles = window.getComputedStyle(document.getElementById(ele), null);\n" +
            "    var lh = parseInt(styles.lineHeight, 10);\n" +
            "    var h = parseInt(styles.height, 10);\n" +
            "    var lc = Math.round(h / lh);\n" +
            "    return lc;\n" +
            "}\n" +
            "\n" +
            "//展示参数\n" +
            "function showParam() {\n" +
            "    var event = window.event || arguments[0];\n" +
            "\n" +
            "    target = event.srcElement || event.target;\n" +
            "\n" +
            "    var formParam = document.createElement(\"span\")\n" +
            "    formParam.innerHTML = \"&nbsp;<input type=\\\"text\\\"  onblur='formParam()'/>\";\n" +
            "    insertAfter(formParam, target);\n" +
            "\n" +
            "}\n" +
            "\n" +
            "\n" +
            "//格式化参数\n" +
            "function formParam() {\n" +
            "    var event = window.event || arguments[0];\n" +
            "\n" +
            "    target = event.srcElement || event.target;\n" +
            "\n" +
            "\n" +
            "    if (target.parentNode.parentNode.getElementsByTagName(\"table\").length == 0) {\n" +
            "        return\n" +
            "    }\n" +
            "\n" +
            "    //寻找url\n" +
            "    var url = target.value;\n" +
            "    if (url.trim().length == 0) {\n" +
            "        return;\n" +
            "    }\n" +
            "    var json = url2json(url);\n" +
            "\n" +
            "\n" +
            "    //寻找table\n" +
            "    var paramLists = target.parentNode.parentNode.getElementsByTagName(\"table\")[0].getElementsByTagName(\"tr\");\n" +
            "\n" +
            "\n" +
            "    var len = paramLists.length;\n" +
            "\n" +
            "\n" +
            "    for (var index = 0; index < len; index++) {\n" +
            "        var tds = paramLists[index].getElementsByTagName(\"td\");\n" +
            "\n" +
            "\n" +
            "        if (tds.length > 0) {\n" +
            "            if (json[tds[0].innerText.trim()] != undefined) {\n" +
            "                //映射\n" +
            "                if (\"text\" == tds[3].getElementsByTagName(\"input\")[0].type) {\n" +
            "                    tds[3].getElementsByTagName(\"input\")[0].value = json[tds[0].innerText.trim()]\n" +
            "                }\n" +
            "\n" +
            "            }\n" +
            "\n" +
            "\n" +
            "        }\n" +
            "    }\n" +
            "\n" +
            "\n" +
            "}\n" +
            "\n" +
            "\n" +
            "function url2json(url) {\n" +
            "    url = url == null ? window.location.href : url;\n" +
            "    url = decodeURIComponent(url)\n" +
            "    var search = url.substring(url.lastIndexOf(\"?\") + 1);\n" +
            "    var obj = {};\n" +
            "    var reg = /([^?&=]+)=([^?&=]*)/g;\n" +
            "    search.replace(reg, function (rs, $1, $2) {\n" +
            "        var name = decodeURIComponent($1);\n" +
            "        var val = decodeURIComponent($2);\n" +
            "        val = String(val);\n" +
            "        obj[name] = val;\n" +
            "        return rs;\n" +
            "    });\n" +
            "    if (JSON.stringify(obj) == \"{}\") {\n" +
            "        obj = JSON.parse(url);\n" +
            "    }\n" +
            "    return obj;\n" +
            "}\n" +
            "\n" +
            "\n" +
            "function insertAfter(newEl, targetEl) {\n" +
            "    var parentEl = targetEl.parentNode;\n" +
            "\n" +
            "    if (parentEl.lastChild == targetEl) {\n" +
            "        parentEl.appendChild(newEl);\n" +
            "    } else {\n" +
            "        parentEl.insertBefore(newEl, targetEl.nextSibling);\n" +
            "    }\n" +
            "}\n" +
            "\n" +
            "\n" +
            "var BASE_PATH_URL = \"\";\n" +
            "var BASE_PATH_URL_STR = \"BASE_PATH_URL\";\n" +
            "\n" +
            "\n" +
            "function isOK(url) {\n" +
            "    if (BASE_PATH_URL.trim().length != 0) {\n" +
            "        return\n" +
            "    }\n" +
            "    ajax({\n" +
            "        type: \"GET\",\n" +
            "        url: url + \"/index.html\",\n" +
            "        success: function (res, urlParam) {\n" +
            "            if (BASE_PATH_URL.trim().length == 0) {\n" +
            "                BASE_PATH_URL = url;\n" +
            "                window.sessionStorage.setItem(BASE_PATH_URL_STR, BASE_PATH_URL)\n" +
            "            }\n" +
            "\n" +
            "        },\n" +
            "        error: function (res) {\n" +
            "\n" +
            "        }\n" +
            "    })\n" +
            "}\n" +
            "\n" +
            "\n" +
            "//获取统一的路径\n" +
            "function getBaseUrl() {\n" +
            "\n" +
            "\n" +
            "    //第一步本页赋值\n" +
            "    if (BASE_PATH_URL.trim().length != 0) {\n" +
            "        return;\n" +
            "    }\n" +
            "    BASE_PATH_URL = window.sessionStorage.getItem(BASE_PATH_URL_STR);\n" +
            "\n" +
            "    if (BASE_PATH_URL == null) {\n" +
            "        BASE_PATH_URL = \"\";\n" +
            "    }\n" +
            "    //第二步本访问赋值\n" +
            "    if (BASE_PATH_URL.trim().length != 0) {\n" +
            "        return;\n" +
            "    }\n" +
            "\n" +
            "\n" +
            "    let host = window.location.host\n" +
            "    let urlTotal = window.location.href;\n" +
            "    var hostArr = urlTotal.split(host);\n" +
            "    if (hostArr.length != 2) {\n" +
            "        return\n" +
            "    }\n" +
            "    var baseUrl = hostArr[0] + host;\n" +
            "\n" +
            "    var urlArr = hostArr[1].split(\"/\")\n" +
            "\n" +
            "    for (var key in urlArr) {\n" +
            "\n" +
            "\n" +
            "        if (urlArr[key].length == 0) {\n" +
            "            isOK(baseUrl);\n" +
            "\n" +
            "        } else {\n" +
            "            baseUrl += \"/\" + urlArr[key];\n" +
            "            isOK(baseUrl);\n" +
            "        }\n" +
            "\n" +
            "\n" +
            "    }\n" +
            "\n" +
            "    window.clearTimeout(timeoutEvent)\n" +
            "\n" +
            "}\n" +
            "\n" +
            "\n" +
            "var timeoutEvent = window.setTimeout(getBaseUrl, 1000);\n" +

            "//更改格式输出\n" +
            "function changeFormat() {\n" +
            "    let event = window.event || arguments[0];\n" +
            "\n" +
            "    let target = event.srcElement || event.target;\n" +
            "\n" +
            "    let parent = target.parentNode;\n" +
            "    let childArr = [];\n" +
            "    let childNodes = parent.parentNode.childNodes;\n" +
            "\n" +
            "    let nextStartFlag = false;\n" +
            "    let preElementFlag = false;\n" +
            "    let newHtml = \"\";\n" +
            "    for (let i = 0, len = childNodes.length; i < len; i++) {\n" +
            "        if (childNodes[i] == parent) {\n" +
            "            nextStartFlag = true;\n" +
            "        } else if (nextStartFlag) {\n" +
            "            newHtml = newHtml + \"\\n\" + childNodes[i].textContent;\n" +
            "            if (childNodes[i].tagName == \"PRE\") {\n" +
            "                preElementFlag = true;\n" +
            "\n" +
            "            }\n" +
            "            childArr.push(childNodes[i])\n" +
            "        }\n" +
            "    }\n" +
            "\n" +
            "\n" +
            "    let newElement;\n" +
            "    if (preElementFlag) {\n" +
            "        newElement = document.createElement('p');\n" +
            "    } else {\n" +
            "        newElement = document.createElement('pre');\n" +
            "\n" +
            "    }\n" +
            "\n" +
            "    newElement.innerHTML = newHtml.replace(/(\\n)+/g, \"\\n\");\n" +
            "\n" +
            "    for (let key in childArr) {\n" +
            "        parent.parentElement.removeChild(childArr[key])\n" +
            "    }\n" +
            "    parent.parentElement.appendChild(newElement);\n" +
            "\n" +
            "\n" +
            "}" +
            "\n";
    private static final Map<String, SearchInfo> SEARCH_INFO_CACHE = new HashMap<>();
    private static Boolean WINDOWS_SYSTEM_FLAG = Boolean.TRUE;

    static {
        File file = new File(JAR_SAVE_FILE);
        if (!file.exists()) {
            file.mkdirs();
        }

        file = new File(TMP_FILE_PATH);
        if (!file.exists()) {
            file.mkdirs();
        }

        if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
            WINDOWS_SYSTEM_FLAG = Boolean.FALSE;
        }


    }

    /**
     * 生成文档
     *
     * @param packageName 包名
     * @throws IOException
     */
    public static void getDoc(String packageName) throws IOException {

        getDoc(packageName, new ArrayList<>());
        //增加http的服务自动的添加
//		AutoRegisterConfigConfig.setJavaDocPackageName(packageName);

    }

    public static void getDoc(String packageName, List<File> files) throws IOException {
        if ((packageName == null || packageName.isEmpty()) && files.isEmpty()) {
            return;
        }


        Set<Class<?>> allAnnotations = new HashSet<>();
        allAnnotations.add(RestController.class);

        if (packageName != null && !packageName.isEmpty()) {
            for (String packName : packageName.split(",")) {
                files.addAll(scannerFile(packName, allAnnotations));
            }
        }

        if (files.isEmpty()) {

            return;
        }


        String docFilesName = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        if (WINDOWS_SYSTEM_FLAG) {
            docFilesName = docFilesName.substring(1);
        }


        File docFile = new File(getCurrentDicPath());
        if (!docFile.exists()) {
            docFile.mkdirs();
        }

        //获取javadoc命令
        List<String> javaDocExecArr = new ArrayList<>();
        javaDocExecArr.add("-doclet");
//		javaDocExecArr.add(StandardDoclet.class.getName());
//        javaDocExecArr.add(Doclet.class.getName());
        javaDocExecArr.add("-d");
        javaDocExecArr.add(docFile.getAbsolutePath());
        javaDocExecArr.add("-quiet");
        javaDocExecArr.add("-windowtitle");
        javaDocExecArr.add("开发文档");
        javaDocExecArr.add("-nohelp");
        javaDocExecArr.add("-nodeprecated");
        javaDocExecArr.add("-nosince");
        javaDocExecArr.add("-notree");
        javaDocExecArr.add("-notimestamp");
        javaDocExecArr.add("-encoding");
        javaDocExecArr.add("utf-8");
        javaDocExecArr.add("-charset");
        javaDocExecArr.add("utf-8");
        javaDocExecArr.add("--allow-script-in-comments");

        List<String> fileGenerateNames = new ArrayList<>();
        for (File file : files) {
            fileGenerateNames.add(normalTemplate2CustomerTemplate(new File(file.getAbsolutePath())));

        }

        javaDocExecArr.addAll(fileGenerateNames);

        //生成javaDoc
        ToolProvider.getSystemDocumentationTool().run(System.in, System.err,
                System.out, javaDocExecArr.toArray(new String[javaDocExecArr.size()]));

        //增加部分系统无法生成，直接执行指令
//        if (docFile.listFiles().length == 0) {
            System.err.println("javadoc -d  " + docFile.getAbsolutePath() + "  " + fileGenerateNames.stream().collect(Collectors.joining(" ")) + " -windowtitle 开发文档   -nohelp  -nodeprecated  -nosince -notree -notimestamp --allow-script-in-comments -encoding utf-8 -charset utf-8  -classpath \"" + System.getProperty("java.class.path").replaceAll("(\\s+)", "") + "\"");
//        }


        //拷贝 即刻生效
        File destinationFiles = new File(docFilesName.replace("classes/", "resources" + STATIC_FILE_NAME));
        if (!destinationFiles.exists()) {
            destinationFiles.mkdirs();
        }

        String cmd;

        if (WINDOWS_SYSTEM_FLAG) {
            cmd = "cmd /k   xcopy \"" + docFile.getAbsolutePath() + "\"  \"" + destinationFiles.getAbsolutePath() + "\" /S /y";

        } else {
            cmd = "cp -r " + docFile.getAbsolutePath() + " " + destinationFiles.getAbsolutePath().replace(STATIC_FILE_NAME, "");

        }


        Thread copyThread = new Thread(() -> {
            try {

                try {
                    //避免原始文件被新生成的文件替换
                    Thread.sleep(10000);
                } catch (InterruptedException e) {

                }

                //增加文件的替换
                replaceScriptFile(docFile.getAbsolutePath());
                //增加搜索的替换
                replaceSearchFile(docFile.getAbsolutePath());


                Runtime.getRuntime().exec(cmd);


            } catch (Exception e) {

            }

        });
        copyThread.setDaemon(true);
        copyThread.start();
    }

    protected static String getCurrentDicPath() {

        //当前目录上一级就是运行的类
        String className = findMainApplicationClass().getSimpleName();

        if (className.isEmpty()) {
            return "";
        }

        String currentExecClassName = className.split("\\$")[0].replaceAll("\\.", File.separator.equalsIgnoreCase("\\") ? "\\\\" : File.separator) + SUFFIX_NAME;
        String absoluteFiles = getAbsoluteFiles(currentExecClassName, Paths.get(".").toFile());
        String javaDicHome = absoluteFiles.substring(0, absoluteFiles.lastIndexOf(currentExecClassName));
        String resourcesDic = javaDicHome.substring(0, javaDicHome.lastIndexOf("java")) + "resources" + STATIC_FILE_NAME;

        return resourcesDic;
    }

    /**
     * 寻找main方法
     *
     * @return
     */
    private static Class<?> findMainApplicationClass() {
        try {
            StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        } catch (ClassNotFoundException ex) {
        }
        return null;
    }

    /**
     * 替换搜索文件
     */
    private static void replaceSearchFile(String filePath) throws InterruptedException, IOException {


        String searchFileName = "search.js";

        //JDK1.8不支持
        Process exec = Runtime.getRuntime().exec("java -version");
        String systemVersion = new BufferedReader(new InputStreamReader(exec.getErrorStream())).lines().collect(Collectors.joining("\n"));
        if (systemVersion.contains("java version \"1.8")) {
            return;
        }

        File file;

        while (true) {
            file = new File(filePath, searchFileName);
            if (file.exists()) {
                break;
            }
        }

        //检测是否存在
        StringBuilder searchFile = new StringBuilder();
        new BufferedReader(new InputStreamReader(new FileInputStream(file)))
                .lines().forEach(x -> {
            if (searchFile.length() == 0) {
                JSONWrapper jsonWrapper = new JSONWrapper();
                searchFile.append("window.onload=function(){\n" +
                        "    document.getElementById(\"search\").setAttribute(\"placeholder\",\"可搜索路径或者说明,模糊匹配利用空格隔开\")\n" +
                        "    document.getElementById(\"search\").value=\"\";\n" +
                        "}\n  " +
                        "var SEARCH_CACHE_LIST =" + jsonWrapper.write(SEARCH_INFO_CACHE) + "\n");

            }
            searchFile.append(x);

            if (x.contains("var newResults = [];")) {
                searchFile.append("            let search_list = [];\n" +
                        "            \n" +
                        "            //空格进行拆分匹配\n" +
                        "            if (request.term.trim().toLowerCase().indexOf(\" \") > -1) {\n" +
                        "                var newFindArr = request.term.trim().toLowerCase().replace(/\\s+/g, \" \").split(\" \");\n" +
                        "\n" +
                        "                //进行多匹配排序\n" +
                        "                var matchCountJson = {};\n" +
                        "                var newFindLen = newFindArr.length;\n" +
                        "                for (var newFindIndex = 0; newFindIndex < newFindLen; newFindIndex++) {\n" +
                        "                    for (let _searchKey in SEARCH_CACHE_LIST) {\n" +
                        "                        if (_searchKey.toLowerCase().indexOf(newFindArr[newFindIndex].trim().toLowerCase()) > -1) {\n" +
                        "\n" +
                        "                            let matchCount = matchCountJson[_searchKey];\n" +
                        "                            if (matchCount == undefined) {\n" +
                        "                                matchCount = 0;\n" +
                        "                            }\n" +
                        "                            matchCountJson[_searchKey] = ++matchCount;\n" +
                        "\n" +
                        "                        }\n" +
                        "\n" +
                        "\n" +
                        "                    }\n" +
                        "                }\n" +
                        "                //按顺序组装\n" +
                        "                if (JSON.stringify(matchCountJson) != \"{}\") {\n" +
                        "\n" +
                        "                    //重新组装最大的\n" +
                        "\n" +
                        "                    var matchCountArr = [];\n" +
                        "\n" +
                        "                    for (let matchCountKey in matchCountJson) {\n" +
                        "                        var matchGroupJson = {}\n" +
                        "                        matchGroupJson[\"name\"] = matchCountKey;\n" +
                        "                        matchGroupJson[\"count\"] = matchCountJson[matchCountKey];\n" +
                        "                        matchCountArr.push(matchGroupJson)\n" +
                        "\n" +
                        "                    }\n" +
                        "                    matchCountArr.sort(function (a, b) {\n" +
                        "\n" +
                        "                        return b[\"count\"] - a[\"count\"]\n" +
                        "                    })\n" +
                        "\n" +
                        "                    var matchCountArrLen = matchCountArr.length\n" +
                        "                    //获取最大的值,只筛选最大的值\n" +
                        "                    var initVal = matchCountArr[0][\"count\"];\n" +
                        "\n" +
                        "                    for (let matchCountArrIndex = 0; matchCountArrIndex < matchCountArrLen; matchCountArrIndex++) {\n" +
                        "\n" +
                        "                        if (matchCountArr[matchCountArrIndex][\"count\"] != initVal) {\n" +
                        "                            break;\n" +
                        "                        }\n" +
                        "                        search_list.push(SEARCH_CACHE_LIST[matchCountArr[matchCountArrIndex][\"name\"]]);\n" +
                        "                    }\n" +
                        "\n" +
                        "                }\n" +
                        "\n" +
                        "            } else {\n" +
                        "                //不是空格精准匹配\n" +
                        "                for (let searchListKey in SEARCH_CACHE_LIST) {\n" +
                        "\n" +
                        "                    if (searchListKey.toLowerCase().indexOf(request.term.trim().toLowerCase()) > -1) {\n" +
                        "                        search_list.push(SEARCH_CACHE_LIST[searchListKey]);\n" +
                        "\n" +
                        "                    }\n" +
                        "\n" +
                        "                }\n" +
                        "            }\n" +
                        "\n" +
                        "            if (search_list.length != 0) {\n" +
                        "                response(search_list);\n" +
                        "                return\n" +
                        "            }");
            } else if (x.trim().endsWith(";") || x.trim().startsWith("//")) {
                searchFile.append("\n");
            }

        });


        FileWriter writer = new FileWriter(file, false);
        writer.write(searchFile.toString());
        writer.flush();
        writer.close();


    }

    /**
     * 替换脚本文件
     */
    private static void replaceScriptFile(String filePath) throws IOException, InterruptedException {

        String scriptFileName = "script.js";

        File file;

        while (true) {
            file = new File(filePath, scriptFileName);
            if (file.exists()) {
                break;
            }
        }

        //检测是否存在
        String allLines = new BufferedReader(new InputStreamReader(new FileInputStream(file)))
                .lines().collect(Collectors.joining("\n"));

        if (allLines.contains("function ajax(opt)")) {
            return;
        }


        FileWriter writer = new FileWriter(file, true);
        writer.write(SUBMIT_STR);
        writer.flush();
        writer.close();


    }

    /**
     * 正常的模板转换渲染的模板
     *
     * @param file 需要修改的文件
     * @return
     * @throws IOException
     */
    private static String normalTemplate2CustomerTemplate(File file) throws IOException {

        List<String> strings = Files.readAllLines(file.toPath());
        StringBuilder allLines = new StringBuilder();

        String line;

        String START_SIGN = "**";
        String FILTER_SIGN = "*";
        String END_SIGN = "/";
        String MESSAGEFORMATER_PARAM_STR = "'''";
        String PARAM_SIGN = " @param";
        String NO_PARAM_SIGN = " <p>";
        String authUrl = "/auth";

        String RETURN_SIGN = " @return";
        String URL_PATH = "/";
        String DIV_ID_SYMBAL = "____";
        String SUBMIT_PARAM_LINE = "&";
        Pattern urlPattern = Pattern.compile("(\\s+)?value(\\s+)?=(\\s+)?\\{([^{]+)(\\s+)?}|\\((\\s+)?\\{([\\w\\W]+)(\\s+)?}");
        Pattern classNameCompile = Pattern.compile("(List<)?([A-Z]\\w+)");
        Pattern packageNameCompile = Pattern.compile("package\\s+([\\w\\.\\s]+)(\\s+)?;");
        Pattern methodPattern = Pattern.compile("(public|private|protected)\\s+(.*)\\s+([\\w]+)(\\s+)?\\(");
        Pattern supportAuthPattern = Pattern.compile("(@(\\s+)?" + UrlAuth.class.getCanonicalName() + ")|(@(\\s+)?" + UrlAuth.class.getSimpleName() + ")");
        Long currentMethod = System.nanoTime();
        Long currentType = System.nanoTime();
        Long currentAppend = System.nanoTime();
        String sendType = String.valueOf(System.nanoTime());
        String methodLocationType = String.valueOf(System.nanoTime());
        String sendBodyType = String.valueOf(System.nanoTime());
        String supportAuthUrlType = String.valueOf(System.nanoTime());
        String noParamsFormat = "%n* @param   _ <code>_</code></br>%n * <button style=\"background-color:#4CAF50;margin-left: 15%%;\" onclick=\"send('','%s','%s','%s')\">发送</button><button  style=\"background-color:#008CBA;\" onclick=\"append('%s')\">增加header</button>  <input style=\"outline-style:none;border:1px solid #ccc;border-radius:3px;padding:4px;\" type=\"text\"\n" +
                "               placeholder=\"输入url参数自动映射\" onblur=\"formParam()\">  <div id=\"'%s'\"></div><a id=\"'%s'\" ></a>";
        String noParamsNewFormat = "%n* @param   _ <code>_</code></br>%n * <button style=\"background-color:#4CAF50;margin-left: 15%%;\" onclick=\"send('','%s','%s','%s')\">发送</button><button  style=\"background-color:#008CBA;\" onclick=\"append('%s')\">增加header</button>   <input style=\"outline-style:none;border:1px solid #ccc;border-radius:3px;padding:4px;\" type=\"text\"\n" +
                "               placeholder=\"输入url参数自动映射\" onblur=\"formParam()\">  <div id=\"'%s'\"></div><a id=\"'%s'\" ></a>";

        String paramFormat = "%n* @param   _ <code>_</code></br>%n *<button style=\"background-color:#4CAF50;margin-left: 15%%%%;\" onclick=\"send({0}," + currentType + "," + currentMethod + ",{1})\">发送</button><button  style=\"background-color:#008CBA;\" onclick=\"append('" + currentAppend + "')\">增加header</button>     <input style=\"outline-style:none;border:1px solid #ccc;border-radius:3px;padding:4px;\" type=\"text\"\n" +
                "               placeholder=\"输入url参数自动映射\" onblur=\"formParam()\">  <div id=\"" + currentAppend + "\"></div><table id=\"" + currentMethod
                + "\">%n   * <tr><th style=\"text-align:left\">请求参数</th> <th style=\"text-align:left\">是否必填</th> <th style=\"text-align:left\">说明</th> <th style=\"text-align:left;color: red;\">测试参数</th> </tr>%n  %s%n  * </table>%n * <p>";
        String paramRepFormat = "\n* <tr><td style=\"text-align:left\"> {0} </td> <td style=\"text-align:left\">%s</td> <td style=\"text-align:left\">{1}</td><td><input type=\"" + sendType + "\" id=\"{2}\"/>" + sendBodyType + "</td></tr>";

        String packageName = "";

        StringBuilder variablesLine = new StringBuilder();
        StringBuilder paramBuild = new StringBuilder();
        StringBuilder paramRequired = new StringBuilder();
        StringBuilder others = new StringBuilder();
        StringBuilder tmpMethod = new StringBuilder();
        StringBuilder submitParamsBuild = new StringBuilder();

        List<String> paramRequiredList = new ArrayList<>();
        List<String> paramSendTypeList = new ArrayList<>();
        List<String> paramSendBodyTypeList = new ArrayList<>();


        List<String> methodArr = new ArrayList<>();
        Map<String, Class> allClassMap = new HashMap<>();

        Boolean paramEndFlag = Boolean.FALSE;
        Boolean START_FLAG = Boolean.FALSE;
        Boolean paramSelectFlag = Boolean.FALSE;
        Boolean noParamFlag = Boolean.FALSE;
        Boolean paramHasReplaceFlag = Boolean.FALSE;

        Boolean isFirstCommint = Boolean.TRUE;
        Boolean parentMappingStartFlag = Boolean.TRUE;
        Boolean isSupportAuthUrlSuffixFlag = Boolean.FALSE;
        Boolean isSupportMultipleAuthUrlSuffixFlag = Boolean.FALSE;
        Boolean isStartSupportAuthUrlSuffixFlag = Boolean.FALSE;
        Boolean isClassDeprecatedFlag = Boolean.FALSE;
        Boolean parentSupportAuthUrlSuffixFlagStatus = null;

        String newClassName = "";
        String apiMethodDoc = "";
        String deprecatedValue = "";
        String oldClassName = file.getName().split("\\.")[0];

        //等于1代表经历过第一次的
        int newClassNameIndex = 0;

        int paramRequiredIndex = 0;

        String parentPath = "";

        int methoIndex = 0;


        for (String str : strings) {


            line = str.trim();
            line = line.length() > 1 ? line.substring(1) : line;
            //增加接口的适配
            if (line.startsWith("ublic class ") || line.startsWith("ublic interface ")) {
                //添加自动默认的注释
                if (!allLines.toString().contains("/**")) {
                    allLines.append("\n/**\n");
                    allLines.append("*");
                    allLines.append(oldClassName);
                    allLines.append("\n*/\n");
                    newClassName = oldClassName;
                    isFirstCommint = Boolean.FALSE;
                }
                parentMappingStartFlag = Boolean.FALSE;
            } else if (str.trim().startsWith("package")) {
                Matcher packageNameMatcher = packageNameCompile.matcher(str.trim());
                if (packageNameMatcher.find()) {
                    packageName = packageNameMatcher.group(1).replaceAll("\\s+", "");

                }

                //排除import *
            } else if (line.startsWith("mport") && !line.contains("*")) {
                try {

                    final Class<?> aClass = Class.forName(line.substring("mport".length(), line.length() - 1).trim());
                    allClassMap.put(aClass.getSimpleName(), aClass);

                } catch (ClassNotFoundException e) {

                }

            } else if (str.trim().equalsIgnoreCase("@Deprecated")) {

                //增加增加方法和类的@Deprecated
                if (parentMappingStartFlag) {
                    allLines.append(str.trim());
                    allLines.append("\n");
                    isClassDeprecatedFlag = Boolean.TRUE;
                } else {
                    deprecatedValue = str.trim() + "\n";
                }
                continue;
            }

            if (parentPath.isEmpty()
                    && parentMappingStartFlag && line.startsWith("RequestMapping")) {
                Matcher urlMatcher = urlPattern.matcher(line);

                String parentPaths;

                if (urlMatcher.find()) {
                    StringBuilder allPaths = new StringBuilder();

                    if (urlMatcher.group(4) != null) {

                        for (String _url : urlMatcher.group(4).split(",")) {
                            if (allPaths.length() != 0) {
                                allPaths.append(",");
                            }
                            allPaths.append(URL_PATH + _url.trim() + URL_PATH);
                        }
                    }

                    if (urlMatcher.group(7) != null) {


                        for (String _url : urlMatcher.group(7).split(",")) {
                            if (allPaths.length() != 0) {
                                allPaths.append(",");
                            }
                            allPaths.append(URL_PATH + _url.trim() + URL_PATH);
                        }

                    }

                    parentPaths = allPaths.toString();

                } else {

                    parentPaths = URL_PATH + line.split("\"")[1].trim() + URL_PATH;
                }

                parentPath = parentPaths;

            }

            //更换文件名称为汉字的说明
            if (line.contains(oldClassName) && !newClassName.isEmpty()) {
                str = str.replaceAll(oldClassName, newClassName);


            }


            if (line.startsWith(START_SIGN)) {
                if (isFirstCommint) {
                    allLines.append(str);
                    allLines.append("\n");
                    newClassNameIndex = 1;
                } else {
                    START_FLAG = Boolean.TRUE;

                }
                continue;
            } else if (line.equals(END_SIGN)) {


                if (isFirstCommint) {
                    allLines.append(str);
                    allLines.append("\n");
                    isFirstCommint = Boolean.FALSE;

                    continue;
                }


                if (!paramHasReplaceFlag) {
                    //参数结束
                    paramEndFlag = Boolean.TRUE;
                    if (paramBuild.length() != 0) {
                        //组合参数

                        submitParamsBuild.append(MESSAGEFORMATER_PARAM_STR);
                        variablesLine.append(MessageFormat.format(String.format(paramFormat, paramBuild.toString()), submitParamsBuild.toString(), methoIndex++));
                        submitParamsBuild.delete(0, submitParamsBuild.length());
                    }
                }


                START_FLAG = Boolean.FALSE;
                continue;

            } else if (line.equals(FILTER_SIGN)) {
                continue;

            } else if (line.equals(NO_PARAM_SIGN)) {
                //排除类上的分割注解
                if (!parentMappingStartFlag) {
                    noParamFlag = Boolean.TRUE;

                }
                continue;
            } else if (supportAuthPattern.matcher(str).find()) {
                if (parentMappingStartFlag) {
                    isStartSupportAuthUrlSuffixFlag = Boolean.TRUE;
                }
                isSupportAuthUrlSuffixFlag = Boolean.TRUE;

                if (line.contains("true")) {
                    isSupportMultipleAuthUrlSuffixFlag = Boolean.TRUE;
                } else {
                    isSupportMultipleAuthUrlSuffixFlag = Boolean.FALSE;
                }

                //加入父类的权限状态
                if (parentMappingStartFlag) {
                    parentSupportAuthUrlSuffixFlagStatus = isSupportMultipleAuthUrlSuffixFlag;
                }

                //取出路径进行编辑
                if (methodArr.size() == 2) {
                    String allUrls = methodArr.get(1);
                    StringBuilder newAllUrls = new StringBuilder();
                    for (String _u : allUrls.split(",")) {
                        if (_u.endsWith(authUrl)) {
                            newAllUrls.append(_u);
                            continue;
                        }

                        if (newAllUrls.length() > 0) {
                            newAllUrls.append(",");
                        }

                        newAllUrls.append((_u + URL_PATH + authUrl).replaceAll(
                                "/{2,}", URL_PATH));

                        if (isSupportMultipleAuthUrlSuffixFlag) {

                            newAllUrls.append(",");
                            newAllUrls.append(_u);
                            //恢复父亲初始化的例子
                            if (parentSupportAuthUrlSuffixFlagStatus != null) {
                                isSupportMultipleAuthUrlSuffixFlag = parentSupportAuthUrlSuffixFlagStatus;
                            }
                        }

                    }
                    methodArr.set(1, newAllUrls.toString());

                    //更新路径的地址
                    noParamsNewFormat = noParamsNewFormat.replaceAll(supportAuthUrlType, newAllUrls.toString());
                    String allVariables = variablesLine.toString().replaceAll(supportAuthUrlType, newAllUrls.toString());
                    variablesLine.delete(0, variablesLine.length());
                    variablesLine.append(allVariables);

                }


                continue;
            } else if (paramSelectFlag) {
                tmpMethod.append(str);
                tmpMethod.append("\n");

                //增加接口对应的文档结束 普通方法{ 接口 );
                if (line.endsWith("{") || line.endsWith(");")) {


                    paramRequired.append(str, 0, str.lastIndexOf(")"));

                    String params = paramRequired.toString().replaceAll("\",", " ");


                    for (String s : params.split(",")) {

                        String _snedTypeStr = "";

                        if (s.toLowerCase().contains("false")) {
                            paramRequiredList.add("否");
                        } else {
                            paramRequiredList.add("<span style=\"color:red\">*是*</span>");
                        }

                        if (s.contains("MultipartFile")) {
                            paramSendTypeList.add("file");

                        } else if (s.contains("@RequestBody")) {

                            paramSendTypeList.add("hidden");

                            String className = s.substring(s.indexOf("@RequestBody") + ("@RequestBody").length());
                            if (className != null) {

                                String[] classNameArr = className.split("\\s");

                                for (String _classNameTmp : classNameArr) {
                                    if (_classNameTmp.trim().isEmpty()) {
                                        continue;
                                    }
                                    Matcher classNameMatcher = classNameCompile.matcher(_classNameTmp.trim());
                                    if (classNameMatcher.find()) {
                                        className = classNameMatcher.group(2);
                                        break;
                                    }
                                }

                            }
                            Class aClass = allClassMap.get(className);

                            if (aClass != null) {
                                String classJsonBody = getAllFields(aClass);
                                //进行反解实体类
                                _snedTypeStr = "<pre contenteditable=\"true\" > " + formatJson(classJsonBody) +
                                        "</pre>";

                            }

                        } else {

                            paramSendTypeList.add("text");
                        }

                        paramSendBodyTypeList.add(_snedTypeStr);

                    }

                    //最后的统一参数的格式化
                    if (methodArr.size() == 2) {
                        //最后更新路径的地址
                        noParamsNewFormat = noParamsNewFormat.replaceAll(supportAuthUrlType, methodArr.get(1));
                        String allVariables = variablesLine.toString().replaceAll(supportAuthUrlType, methodArr.get(1));
                        variablesLine.delete(0, variablesLine.length());
                        variablesLine.append(allVariables);
                    }

                    //进行再次格式化
                    variablesLine.append("\n");
                    if (others.length() != 0) {
                        if (noParamFlag) {
                            variablesLine.append("\n*@param \"\" \"\"<br/>");
                        }
                        variablesLine.append("\n * <span style=\"color:red\">举例说明：</span>  <button style=\"padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px;color:#fff;background-color: #5cb85c;border-color: #4cae4c;\" onclick=\"changeFormat()\">格式化</button> \n  * <p> \n<br/>\n");
                        variablesLine.append(others.toString());
                        variablesLine.append("\n\n");
                    }


                    String result = String.format(MessageFormat.format(variablesLine.toString(), methodArr.toArray()), paramRequiredList.toArray());


                    //判断是否有变量
                    if (!result.contains("<table")) {
                        result += noParamsNewFormat;
                    }


                    //再次修改变量的输入格式
                    for (String _tmpType : paramSendTypeList) {
                        result = result.replaceFirst(sendType, _tmpType);
                    }
                    //再次修改变量的输入格式
                    for (String _tmpType : paramSendBodyTypeList) {

                        result = result.replaceFirst(sendBodyType, _tmpType);

                    }

                    String methodLocationUrl;


                    //添加自定义的修改方法
                    allLines.append("/**\n");

                    //修改location的url
                    Matcher methodMatcher = methodPattern.matcher(tmpMethod.toString());
                    String tmpMethodName = "";
                    if (methodMatcher.find()) {
                        tmpMethodName = methodMatcher.group(3);
                        allLines.append(result.replaceAll(methodLocationType, "#" + tmpMethodName + "()"));
                        //新增接口方法结束的适配
                        methodLocationUrl = methodMatcher.group() + (line.endsWith(");") ? ");" : ") {");
                    } else {
                        allLines.append(result.replaceAll(methodLocationType, "javascript:void(0)"));
                        methodLocationUrl = tmpMethod.toString();
                    }

                    allLines.append("*/\n");

                    //增加方法@Deprecated
                    boolean isMethodDeprecatedFlag = false;
                    if (!deprecatedValue.isEmpty()) {
                        allLines.append(deprecatedValue);
                        deprecatedValue = "";
                        isMethodDeprecatedFlag = true;
                    }


                    //增加java9的搜索集合
                    if (!packageName.isEmpty() && methodArr.size() == 2 &&
                            //增加@Deprecated的过滤
                            !tmpMethodName.isEmpty() && !isClassDeprecatedFlag
                            && !isMethodDeprecatedFlag) {
                        SearchInfo searchInfo = new SearchInfo();
                        searchInfo.setP(packageName);
                        searchInfo.setC(newClassName);
                        searchInfo.setCategory("Members");
                        searchInfo.setL(tmpMethodName + "()");
                        SEARCH_INFO_CACHE.put(methodArr.get(1)
                                , searchInfo);
                        //添加api说明
                        if (!apiMethodDoc.isEmpty()) {
                            SEARCH_INFO_CACHE.put(apiMethodDoc, searchInfo.copy());
                        }

                    }


                    //修改为无入参数的方法
                    allLines.append(methodLocationUrl);


                    //所有进行初始化 进行下一轮
                    paramRequired.delete(0, paramRequired.length());
                    variablesLine.delete(0, variablesLine.length());
                    paramBuild.delete(0, paramBuild.length());
                    others.delete(0, others.length());
                    tmpMethod.delete(0, tmpMethod.length());

                    paramRequiredList.clear();
                    paramSendTypeList.clear();
                    paramSendBodyTypeList.clear();
                    methodArr.clear();
                    START_FLAG = Boolean.FALSE;
                    paramEndFlag = Boolean.FALSE;
                    paramSelectFlag = Boolean.FALSE;
                    paramHasReplaceFlag = Boolean.FALSE;
                    noParamFlag = Boolean.FALSE;

                    if (!isStartSupportAuthUrlSuffixFlag) {
                        isSupportAuthUrlSuffixFlag = Boolean.FALSE;
                        isSupportMultipleAuthUrlSuffixFlag = Boolean.FALSE;

                    }

                    paramRequiredIndex = 0;

                } else {
                    if (paramRequiredIndex == 0) {
                        paramRequired.append(str.substring(str.indexOf("(") + 1));
                    } else {
                        paramRequired.append(str);
                    }
                }

                paramRequiredIndex++;
            } else {
                if (!(str.trim().startsWith("*") || (line.startsWith("GetMapping") || line.startsWith("RequestMapping")
                        || line.startsWith("PostMapping"))) || isFirstCommint) {
                    if (!str.trim().startsWith("@")) {
                        allLines.append(str);
                        if (newClassNameIndex == 1 && isFirstCommint) {
                            if (parentMappingStartFlag) {
                                //处理特殊符号
                                newClassName = str.replaceAll("\\s|\\*", "").replaceAll(
                                        "(\\(|\\)|\\{|}|\\[|]|-)", "_").trim();

                            } else {
                                newClassName = oldClassName;
                            }
                            newClassNameIndex++;

                        }
                        allLines.append("\n");

                    }
                }
            }


            if (START_FLAG) {
                //方法
                if (variablesLine.length() == 0) {

                    variablesLine.append("\n * <p>\n * <span>API说明：<a style=\"color:blue\">");
                    variablesLine.append(line);
                    variablesLine.append("</a></span> \n  * <br/>\n * <span>请求方式：<a style = \"color:blue\">{0}");
                    variablesLine.append("</a></span>\n * <br/>\n * <span>URL地址： <a href=\"" + methodLocationType + "\">{1}</a></span>\n * <br/>\n  * </p >\n ");

                    //添加api说明
                    apiMethodDoc = line.trim();

                } else {

                    if (paramEndFlag || noParamFlag) {
                        //排除return 的语句
                        if (!line.equals(RETURN_SIGN)) {

                            String othersValue = getJavaDocExplain(line);
                            others.append(othersValue.isEmpty() ? line.replaceAll("\\{", "'{'") : othersValue);
                            others.append("<br/>");
                        }

                    } else {

                        //param 优化
                        if (line.startsWith(PARAM_SIGN)) {


                            String[] _paramsSplitArr = (line.split(PARAM_SIGN).length <= 1) ? new String[]{""} : line.split(PARAM_SIGN)[1].split("\\s+");
                            //_repSign的组成为 name-value
                            List<String> _repSign = new ArrayList<>();
                            //添加 name
                            for (String _paramsSplit : _paramsSplitArr) {
                                if (!_paramsSplit.trim().isEmpty()) {
                                    _repSign.add(_paramsSplit);
                                    break;
                                }
                            }

                            String paramValueStr = (line.split(PARAM_SIGN).length <= 1) ? "" : (line.split(PARAM_SIGN)[1].trim().substring(_repSign.get(0).length()));


                            String paramJavaDocExplain = getJavaDocExplain(paramValueStr);
                            if (!paramJavaDocExplain.isEmpty()) {
                                paramValueStr = paramJavaDocExplain;
                            }
                            paramValueStr = paramValueStr.replaceAll("\\{", "﹛").
                                    replaceAll("}", "﹜");


                            //其余的进行组合为value,replaceAll的{排除MessageFormat的错误
                            //当参数为空时候，把key复制为value
                            if (paramValueStr.isEmpty()) {
                                _repSign.add(_repSign.get(0));
                            } else {
                                _repSign.add(paramValueStr);
                            }


                            //添加发送请求input的参数Id
                            String __tmpParamName = _repSign.get(0);

                            _repSign.add(__tmpParamName + methoIndex);

                            if (submitParamsBuild.length() != 0) {
                                submitParamsBuild.append(SUBMIT_PARAM_LINE);
                            } else {
                                submitParamsBuild.append(MESSAGEFORMATER_PARAM_STR);
                            }
                            submitParamsBuild.append(__tmpParamName);

                            paramBuild.append(MessageFormat.format(paramRepFormat, _repSign.toArray()));

                        } else {

                            //排除return 的语句
                            if (!line.equals(RETURN_SIGN)) {
                                String othersValue = getJavaDocExplain(line);
                                others.append(othersValue.isEmpty() ? line.replaceAll("\\{", "'{'") : othersValue);
                                others.append("<br/>");
                            }
                            //参数结束
                            paramEndFlag = Boolean.TRUE;
                            paramHasReplaceFlag = Boolean.TRUE;

                            if (paramBuild.length() != 0) {
                                //组合参数
                                submitParamsBuild.append(MESSAGEFORMATER_PARAM_STR);
                                variablesLine.append(MessageFormat.format(String.format(paramFormat, paramBuild.toString()), submitParamsBuild.toString(), methoIndex++));
                                submitParamsBuild.delete(0, submitParamsBuild.length());
                            }
                        }


                    }


                }

            } else {


                //方法
                if (((line.startsWith("GetMapping") || line.startsWith("RequestMapping")
                        || line.startsWith("PostMapping"))) && variablesLine.length() != 0) {
                    String pushType;
                    if (line.toLowerCase().contains("getmapping") || line.toLowerCase().contains("requestmethod.get")) {
                        pushType = "GET";
                        methodArr.add(pushType);

                    } else if (line.toLowerCase().contains("postmapping") || line.toLowerCase().contains("requestmethod.post")) {
                        pushType = "POST";
                        methodArr.add(pushType);
                    } else {
                        methodArr.add("POST/GET(皆可)");
                        pushType = "POST";
                    }

                    Matcher urlMatcher = urlPattern.matcher(line);

                    String paths;

                    if (urlMatcher.find()) {
                        StringBuilder allPaths = new StringBuilder();

                        if (urlMatcher.group(4) != null) {

                            for (String _url : urlMatcher.group(4).split(",")) {
                                if (allPaths.length() != 0) {
                                    allPaths.append(",");
                                }

                                allPaths.append((parentPath + URL_PATH + _url.trim())
                                        .replaceAll("[\\s\"]+", "").replaceAll(
                                                "/{2,}", URL_PATH));
                            }
                        }

                        if (urlMatcher.group(7) != null) {


                            for (String _url : urlMatcher.group(7).split(",")) {
                                if (allPaths.length() != 0) {
                                    allPaths.append(",");
                                }
                                allPaths.append((parentPath + URL_PATH + _url.trim())
                                        .replaceAll("[\\s\"]+", "").replaceAll(
                                                "/{2,}", URL_PATH));
                            }

                        }

                        paths = allPaths.toString();

                    } else {

                        paths = (parentPath + URL_PATH + line.split("\"")[1].trim())
                                .replaceAll("[\\s\"]+", "").replaceAll(
                                        "/{2,}", URL_PATH);
                    }


                    //路径
                    methodArr.add(paths);

                    //是否打开权限的注解
                    if (methodArr.size() == 2 && isSupportAuthUrlSuffixFlag) {
                        //取出路径进行编辑
                        String allUrls = methodArr.get(1);
                        StringBuilder newAllUrls = new StringBuilder();
                        for (String _u : allUrls.split(",")) {
                            if (_u.endsWith(authUrl)) {
                                newAllUrls.append(_u);
                                continue;
                            }

                            if (newAllUrls.length() > 0) {
                                newAllUrls.append(",");
                            }

                            newAllUrls.append((_u + URL_PATH + authUrl).replaceAll(
                                    "/{2,}", URL_PATH));

                            if (isSupportMultipleAuthUrlSuffixFlag) {

                                newAllUrls.append(",");
                                newAllUrls.append(_u);
                                //恢复父亲初始化的例子
                                if (parentSupportAuthUrlSuffixFlagStatus != null) {
                                    isSupportMultipleAuthUrlSuffixFlag = parentSupportAuthUrlSuffixFlagStatus;
                                }

                            }
                        }
                        methodArr.set(1, newAllUrls.toString());
                        paths = newAllUrls.toString();
                    } else {
                        paths = supportAuthUrlType;
                    }


                    //新增变量中替换请求方法和请求方式
                    String _originalVariable = variablesLine.toString();
                    variablesLine.delete(0, variablesLine.length());
                    variablesLine.append(_originalVariable.replaceAll(String.valueOf(currentMethod), MESSAGEFORMATER_PARAM_STR + paths + MESSAGEFORMATER_PARAM_STR)
                            .replaceAll(String.valueOf(currentType), MESSAGEFORMATER_PARAM_STR + pushType + MESSAGEFORMATER_PARAM_STR)
                            .replaceAll(String.valueOf(currentAppend), MESSAGEFORMATER_PARAM_STR + (DIV_ID_SYMBAL + paths + methoIndex) + MESSAGEFORMATER_PARAM_STR));

                    //替换没有变量的选择
                    noParamsNewFormat = String.format(noParamsFormat, pushType, paths, methoIndex, (DIV_ID_SYMBAL + paths + methoIndex), (DIV_ID_SYMBAL + paths + methoIndex), paths);


                    //下一个必然是参数的可选映射
                    paramSelectFlag = Boolean.TRUE;

                }


            }


        }
        //更换文件也为汉字并且处理特殊符号
        File _tmpSaveFile = new File(TMP_FILE_PATH + newClassName + ".java");

        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(_tmpSaveFile)))) {

            writer.write(allLines.toString());
        }


        return _tmpSaveFile.getAbsolutePath();

    }

    /**
     * 扫描类
     *
     * @param packageName    包路径
     * @param allAnnotations 需要扫描携带的注解类的包
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */

    private static List<File> scannerFile(String packageName, Set<Class<?>> allAnnotations) {
        try {
            return (List<File>) scanner(packageName, allAnnotations).get(SCANNER_FILE_KEY);
        } catch (Exception e) {
            throw new RuntimeException("解析文件类出错" + e);
        }
    }

    /**
     * 扫描类
     *
     * @param packageName    包路径
     * @param allAnnotations 需要扫描携带的注解类的包
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */

    private static Set<Class<?>> scannerClass(String packageName, Set<Class<?>> allAnnotations) {
        try {
            return (Set<Class<?>>) scanner(packageName, allAnnotations).get(SCANNER_CLASS_KEY);

        } catch (Exception e) {
            throw new RuntimeException("解析类包出错" + e);
        }

    }

    /**
     * 扫描包
     *
     * @param packageName    包路径
     * @param allAnnotations 需要扫描携带的注解类的包
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */

    public static Map<String, Object> scanner(String packageName, Set<Class<?>> allAnnotations) throws IOException, ClassNotFoundException {

        Map<String, Object> resultMap = new HashMap<>();

        Set<Class<?>> allClasses = new HashSet<>();

        List<File> allAccordFiles = new ArrayList<>();


        if (packageName == null || packageName.isEmpty()) {
            resultMap.put(SCANNER_CLASS_KEY, allClasses);
            return resultMap;
        }

        String scannerPackageName = packageName.replaceAll("/", ".");

        Enumeration<URL> resource = Thread.currentThread().getContextClassLoader().getResources(packageName.replaceAll("\\.", "/"));
        URL url;
        String protocol;


        while (resource.hasMoreElements()) {
            url = resource.nextElement();
            if (url == null) {
                continue;
            }
            protocol = url.getProtocol();
            if ("file".equals(protocol)) {

                String baseFile;
                //windows处理
                if (WINDOWS_SYSTEM_FLAG) {
                    baseFile = url.getFile().substring(1);
                } else {
                    //默认unix
                    baseFile = url.getFile();
                }

                parseClasses(scannerPackageName, baseFile, allClasses, allAccordFiles, allAnnotations);
            } else if ("jar".equals(protocol)) {
                parseJarClasses((JarURLConnection) url.openConnection(), allClasses, allAccordFiles, allAnnotations);
            }


        }
        resultMap.put(SCANNER_CLASS_KEY, allClasses);
        resultMap.put(SCANNER_FILE_KEY, allAccordFiles);

        return resultMap;

    }


    /**
     * 根据字符串获取java的说明
     *
     * @param text 字符串内容
     * @return
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     */
    private static String getJavaDocExplain(String text) {
        Pattern pattern = Pattern.compile("(.*)\\{@(link|linkplain)(.*)}");
        Matcher matcher = pattern.matcher(text);
        StringBuilder enumsLinkBuilder = new StringBuilder();
        try {
            if (matcher.find()) {
                Class<?> findClass = Class.forName(matcher.group(3).trim());

                if (findClass.isEnum()) {

                    //枚举
                    Object[] enumConstants = findClass.getEnumConstants();
                    for (Object enums : enumConstants) {
                        StringBuilder enumsFileBuilder = new StringBuilder();
                        for (Field field : enums.getClass().getDeclaredFields()) {
                            if (!(field.isEnumConstant() || field.getName().equals("$VALUES"))) {
                                field.setAccessible(true);
                                if (enumsFileBuilder.length() != 0) {
                                    enumsFileBuilder.append(":");
                                }
                                enumsFileBuilder.append(field.get(enums));

                            }


                        }
                        if (enumsFileBuilder.length() == 0) {
                            continue;
                        }
                        //如果没有多个构造参数说明，那么把枚举的定义加上
                        if (!enumsFileBuilder.toString().contains(":")) {
                            enumsFileBuilder.insert(0, enums + ":");
                        }
                        if (enumsLinkBuilder.length() != 0) {
                            enumsLinkBuilder.append(",");
                        }

                        enumsLinkBuilder.append(enumsFileBuilder);


                    }
                } else {

                    for (Field field : findClass.getDeclaredFields()) {

                        if (Modifier.isStatic(field.getModifiers()) && Modifier.isPublic(field.getModifiers())) {
                            if (enumsLinkBuilder.length() != 0) {
                                enumsLinkBuilder.append(",");
                            }
                            enumsLinkBuilder.append(field.getName());
                            enumsLinkBuilder.append(":");
                            enumsLinkBuilder.append(field.get(findClass));


                        }
                    }
                    //判断是否有值,没有的话直接反射私有属性
                    if (enumsLinkBuilder.length() == 0) {

                        //第一次尝试用javadocRead,不行就降级
                        try {
                            //TODO:xxx
//							Map<String, String> javaDocValues = JavaDocReader.read(findClass);
                            Map<String, String> javaDocValues = new HashMap<>();

                            for (Map.Entry<String, String> entry : javaDocValues.entrySet()) {
                                if (enumsLinkBuilder.length() != 0) {
                                    enumsLinkBuilder.append(",");
                                } else {
                                    enumsLinkBuilder.append("'{'\n");
                                }
                                enumsLinkBuilder.append("\"");
                                enumsLinkBuilder.append(entry.getKey());
                                enumsLinkBuilder.append("\"");
                                enumsLinkBuilder.append(":");
                                enumsLinkBuilder.append("\"");
                                //查看值是否有递归操作
                                Matcher childMatcher = pattern.matcher(entry.getValue());
                                if (childMatcher.find()) {
                                    enumsLinkBuilder.append(getJavaDocExplain(entry.getValue()));
                                } else {

                                    enumsLinkBuilder.append(entry.getValue().replaceAll(
                                            "(\\(|\\)|\\{|}|\\[|]|-|\")", "_"));
                                }
                                enumsLinkBuilder.append("\"");

                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                            for (Field field : findClass.getDeclaredFields()) {

                                boolean isPrivateAttributeFlag = !Modifier.isStatic(field.getModifiers()) &&
                                        (Modifier.isPrivate(field.getModifiers()) ||
                                                Modifier.isProtected(field.getModifiers()));
                                if (isPrivateAttributeFlag) {
                                    field.setAccessible(true);
                                    if (enumsLinkBuilder.length() != 0) {
                                        enumsLinkBuilder.append(",");
                                    } else {
                                        enumsLinkBuilder.append("'{'\n");
                                    }
                                    enumsLinkBuilder.append("\"");
                                    enumsLinkBuilder.append(field.getName());
                                    enumsLinkBuilder.append("\"");
                                    enumsLinkBuilder.append(":");
                                    enumsLinkBuilder.append("\"");
                                    enumsLinkBuilder.append("\"");


                                }
                            }


                        }


                        if (enumsLinkBuilder.length() != 0) {
                            enumsLinkBuilder.append("}\n");
                            //格式化
                            String json = enumsLinkBuilder.toString();
                            enumsLinkBuilder.delete(0, enumsLinkBuilder.length());
                            enumsLinkBuilder.append(formatJson(json));

                        }


                    }


                }
                enumsLinkBuilder.insert(0, matcher.group(1));
            }
        } catch (Exception e) {

        }
        return enumsLinkBuilder.toString();
    }

    /**
     * 解析jar的classes
     *
     * @param jarURLConnection      jar的连接池
     * @param originalClasses       原始的classes类
     * @param originalAccordFiles   原始的符合的类
     * @param parseSpecialClassType 解析指定的类型
     * @return
     * @throws ClassNotFoundException
     */
    private static Set<Class<?>> parseJarClasses(JarURLConnection jarURLConnection, Set<Class<?>> originalClasses, List<File> originalAccordFiles, Set<Class<?>> parseSpecialClassType) throws ClassNotFoundException, IOException {

        Set<Class<?>> _allClasses;

        List<File> _allAccordFiles;


        if (originalClasses != null) {
            _allClasses = originalClasses;
        } else {
            _allClasses = new HashSet<>();
        }

        if (originalAccordFiles != null) {
            _allAccordFiles = originalAccordFiles;
        } else {
            _allAccordFiles = new ArrayList<>();

        }


        if (jarURLConnection == null) {
            return _allClasses;
        }

        JarFile jarFile = jarURLConnection.getJarFile();
        Enumeration<JarEntry> entries = jarFile.entries();

        JarEntry jarEntry;
        String jarName;
        while (entries.hasMoreElements()) {
            jarEntry = entries.nextElement();
            if (jarEntry == null) {
                continue;
            }
            jarName = jarEntry.getName();
            if (jarName.endsWith(".class")) {


                int _index = jarName.lastIndexOf("/");


                String fileName = jarName.substring(_index + 1, jarName.lastIndexOf("."));

                //内部类直接过滤
                if (fileName.contains("$")) {
                    fileName = fileName.split("\\$")[0];
                }

                if (addClasses(loadClasses(jarName.substring(0, _index).replaceAll("/", "."), fileName),
                        _allClasses, parseSpecialClassType)) {

                    Files.copy(jarFile.getInputStream(jarEntry), Paths.get(JAR_SAVE_FILE + fileName + SUFFIX_NAME), StandardCopyOption.REPLACE_EXISTING);
                    _allAccordFiles.add(new File(JAR_SAVE_FILE + fileName + SUFFIX_NAME));

                }


            }


        }

        return _allClasses;


    }

    /**
     * 解析classes
     *
     * @param scannerPackagerName   原始扫包路径
     * @param parsePackagerName     子解析的路径
     * @param originalClasses       原始的classes类
     * @param originalAccordFiles   原始的符合的类
     * @param parseSpecialClassType 解析指定的类型
     * @return
     * @throws ClassNotFoundException
     */
    private static Set<Class<?>> parseClasses(String scannerPackagerName, String parsePackagerName, Set<Class<?>> originalClasses, List<File> originalAccordFiles, Set<Class<?>> parseSpecialClassType) throws ClassNotFoundException {
        Set<Class<?>> _allClasses;

        if (originalClasses != null) {
            _allClasses = originalClasses;
        } else {
            _allClasses = new HashSet<>();
        }


        List<File> _allAccordFiles;


        if (originalAccordFiles != null) {
            _allAccordFiles = originalAccordFiles;
        } else {
            _allAccordFiles = new ArrayList<>();

        }


        if (parsePackagerName == null || parsePackagerName.isEmpty() || scannerPackagerName == null || scannerPackagerName.isEmpty()) {
            return _allClasses;
        }
        File[] files = new File(parsePackagerName).listFiles(x -> x.isFile() && !x.getName().contains("$") && x.getName().endsWith("class") || x.isDirectory());

        for (File file : files) {
            if (file.isFile()) {
                Class<?> needClass = loadClasses(scannerPackagerName, file.getName().split("\\.")[0]);
                if (addClasses(needClass, _allClasses, parseSpecialClassType)) {


                    String absoluteFilePaths = getAbsoluteFiles(needClass.getCanonicalName().replaceAll("\\.", File.separator.equalsIgnoreCase("\\") ? "\\\\" : File.separator) + SUFFIX_NAME, Paths.get(".").toFile());

                    if (absoluteFilePaths.isEmpty()) {
                        continue;
                    }

                    _allAccordFiles.add(new File(absoluteFilePaths));


                }

            } else {

                parseClasses(scannerPackagerName + "." + file.getName().split("\\.")[0], file.getPath(), _allClasses, originalAccordFiles, parseSpecialClassType);
            }


        }


        return _allClasses;
    }

    /**
     * 根据路径获取对应的文件的绝对路径
     *
     * @param fileName 文件的地址
     * @param pathFile 文件的根目录
     * @return
     */
    private static String getAbsoluteFiles(String fileName, File pathFile) {
        File[] files = pathFile.listFiles();
        String resultPath = "";
        for (File file : files) {
            if (!resultPath.isEmpty()) {
                break;
            }
            if (file.isDirectory()) {
                resultPath = getAbsoluteFiles(fileName, file);
            } else if (file.getName().endsWith(".java") && file.getAbsolutePath().endsWith(fileName)) {
                resultPath = file.getAbsolutePath();
                break;
            }
        }

        return resultPath;

    }

    /**
     * 加载class
     *
     * @param scannerPackageName 扫包的路径
     * @param fileName           包的名称
     * @return
     * @throws ClassNotFoundException
     */
    private static Class<?> loadClasses(String scannerPackageName, String fileName) throws ClassNotFoundException {
        return Class.forName(scannerPackageName + "." + fileName);
    }

    /**
     * 添加classes
     *
     * @param aClass                需要添加的classes
     * @param allClasses            需要添加的classes类集合
     * @param parseSpecialClassType 解析指定的类型
     * @param aClass
     */
    private static boolean addClasses(Class<?> aClass, Set<Class<?>> allClasses, Set<Class<?>> parseSpecialClassType) {

        boolean _addSuccess = false;

        if (parseSpecialClassType == null) {
            allClasses.add(aClass);
            _addSuccess = true;
        } else {
            Annotation annotation;
            for (Class cl : parseSpecialClassType) {
                annotation = aClass.getAnnotation(cl);

                if (annotation != null) {
                    allClasses.add(aClass);
                    _addSuccess = true;
                    break;
                }

            }
        }


        return _addSuccess;

    }

    /**
     * 根据类获取所有属性
     *
     * @param aClass
     * @return
     */
    private static String getAllFields(Class<?> aClass) {

        StringBuilder fieldBuild = new StringBuilder("{");

        int indexLength = fieldBuild.length();
        Field[] fieldArr = aClass.getDeclaredFields();

        for (Field field : fieldArr) {

            if (Modifier.isFinal(field.getModifiers())) {
                continue;
            }


            if (fieldBuild.length() > indexLength) {
                fieldBuild.append(",");
            }
            fieldBuild.append("\"");
            fieldBuild.append(field.getName());
            fieldBuild.append("\":\"\"");


        }

        while (!aClass.getCanonicalName().equals(Object.class.getCanonicalName())) {
            aClass = aClass.getSuperclass();

            fieldArr = aClass.getDeclaredFields();
            for (Field field : fieldArr) {
                if (Modifier.isProtected(field.getModifiers()) || Modifier.isProtected(field.getModifiers())
                        && !Modifier.isFinal(field.getModifiers())) {
                    if (fieldBuild.length() > indexLength) {
                        fieldBuild.append(",");
                    }
                    fieldBuild.append("\"");
                    fieldBuild.append(field.getName());
                    fieldBuild.append("\":\"\"");
                }


            }


        }
        fieldBuild.append("}");

        return fieldBuild.toString();
    }

    /**
     * 格式化json字符串
     *
     * @param jsonStr
     * @return
     */
    private static String formatJson(String jsonStr) {
        if (null == jsonStr || "".equals(jsonStr)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        char last = '\0';
        char current = '\0';
        int indent = 0;
        for (int i = 0; i < jsonStr.length(); i++) {
            last = current;
            current = jsonStr.charAt(i);
            switch (current) {
                case '{':
                case '[':
                    sb.append(current);
                    sb.append('\n');
                    indent++;
                    addIndentBlank(sb, indent);
                    break;
                case '}':
                case ']':
                    sb.append('\n');
                    indent--;
                    addIndentBlank(sb, indent);
                    sb.append(current);
                    break;
                case ',':
                    sb.append(current);
                    if (last != '\\') {
                        sb.append('\n');
                        addIndentBlank(sb, indent);
                    }
                    break;
                default:
                    sb.append(current);
            }
        }

        return sb.toString();
    }

    private static void addIndentBlank(StringBuilder sb, int indent) {
        for (int i = 0; i < indent; i++) {
            sb.append('\t');
        }
    }

    /**
     * 寻找信息的类
     */
    protected static class SearchInfo {
        //packageName
        protected String p;
        //className
        protected String c;
        //lName
        protected String l;
        //category
        protected String category;


        protected SearchInfo copy() {
            SearchInfo copy = new SearchInfo();
            copy.setL(getL());
            copy.setP(getP());
            copy.setC(getC());
            copy.setCategory(getCategory());
            return copy;
        }

        public String getP() {
            return p;
        }

        public void setP(String p) {
            this.p = p;
        }

        public String getC() {
            return c;
        }

        public void setC(String c) {
            this.c = c;
        }

        public String getL() {
            return l;
        }

        public void setL(String l) {
            this.l = l;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(String category) {
            this.category = category;
        }

    }


    /**
     * json转换
     *
     * @param <T>
     */
    private static class JSONWrapper<T> {

        private static final String COMMA = ",";
        private static final String MARKS = "\"";
        private static final String COLON = ":";
        private static final String BRACKET_LEFT = "[";
        private static final String BRACKET_RIGHT = "]";
        private static final String BRACE_LEFT = "{";
        private static final String BRACE_RIGHT = "}";
        private static final String STR_VERSION_UID = "serialVersionUID";
        final StringBuilder json = new StringBuilder();

        private static Map<String, Object> getBeanValue(Object obj) {
            Map<String, Object> map = new HashMap<>();
            try {
                Field[] fields = obj.getClass().getDeclaredFields();
                Object obj2;
                for (Field field : fields) {
                    field.setAccessible(true);
                    obj2 = field.get(obj);
                    field.setAccessible(false);
                    if (obj2 != null) {
                        map.put(field.getName(), obj2);
                    }
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
            }
            return map;
        }

        private static boolean isMap(Object obj) {
            return obj instanceof Map;
        }

        private static boolean isList(Object obj) {
            return obj instanceof List;
        }

        private static boolean isArray(Object obj) {
            return obj.getClass().isArray();
        }

        private static boolean isString(Object obj) {
            return obj instanceof CharSequence || obj instanceof Character;
        }

        private static boolean isNumber(Object obj) {
            return obj instanceof Integer || obj instanceof Boolean || obj instanceof Double || obj instanceof Long
                    || obj instanceof Byte || obj instanceof Float || obj instanceof Short;
        }

        public String write(Map<String, T> jsonMap) {
            try {
                appendMap(jsonMap);
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
            return json.toString();
        }

        private void appendMap(Map<String, T> map) {
            json.append(BRACE_LEFT);
            Iterator<String> keys = map.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                appendObj(key, map.get(key), keys.hasNext());
            }
            json.append(BRACE_RIGHT);
        }

        private void appendObj(String key, Object obj, boolean hasNext) {
            if (obj == null || STR_VERSION_UID.equals(key)) {
                return;
            }
            if (key != null) {
                json.append(MARKS).append(key).append(MARKS).append(COLON);
            }
            if (isNumber(obj)) {
                appendNum(obj);
            } else if (isString(obj)) {
                appendString(obj.toString());
            } else if (isArray(obj)) {
                appendArray(obj);
            } else if (isList(obj)) {
                appendList((List<?>) obj);
            } else if (isMap(obj)) {
                appendMap2((Map<?, ?>) obj);
            } else {
                appendBean(obj);
            }
            if (hasNext) {
                json.append(COMMA);
            }
        }

        private void appendBean(Object obj) {
            json.append(BRACE_LEFT);
            Map<String, Object> map = getBeanValue(obj);
            Iterator<String> keys = map.keySet().iterator();
            String key;
            while (keys.hasNext()) {
                key = keys.next();
                appendObj(key, map.get(key), keys.hasNext());
            }
            json.append(BRACE_RIGHT);
        }

        private void appendMap2(Map<?, ?> map) {
            json.append(BRACKET_LEFT);
            Iterator<?> keys = map.keySet().iterator();
            while (keys.hasNext()) {
                String key = (String) keys.next();
                appendObj(key, map.get(key), keys.hasNext());
            }
            json.append(BRACKET_RIGHT);
        }

        private void appendList(List<?> list) {
            json.append(BRACKET_LEFT);
            int len = list.size();
            for (int i = 0; i < len; i++) {
                appendObj(null, list.get(i), i != (len - 1));
            }
            json.append(BRACKET_RIGHT);
        }

        private void appendArray(Object obj) {
            json.append(BRACKET_LEFT);
            int len = Array.getLength(obj);
            for (int i = 0; i < len; i++) {
                appendObj(null, Array.get(obj, i), i != (len - 1));
            }
            json.append(BRACKET_RIGHT);
        }

        private void appendNum(Object obj) {
            json.append(obj);
        }

        private void appendString(String str) {
            if (str.indexOf("\n") != -1) {
                str = str.replaceAll("\\n", "\\\\n");
            }
            if (str.indexOf("\t") != -1) {
                str = str.replaceAll("\\t", "\\\\t");
            }
            if (str.indexOf("\r") != -1) {
                str = str.replaceAll("\\r", "\\\\r");
            }
            json.append(MARKS).append(str).append(MARKS);
        }

    }

}
